using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Silverlight.Testing;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Rhino.Mocks;
using SLNGP.Common.IoC;
using SLNGP.Core.Genes;
using SLNGP.Core.GeneticPrograms;
using SLNGP.Core.Individuals;
using SLNGP.Core.Test;

namespace SLNGP.Test.CoreTests.Individuals
{
    [TestClass]
    [Tag("Chromosome")]
    public class Chromosome_Test : UnitTestBase<IChromosome, Chromosome>
    {
        #region UnitTestBase methods
        [ClassInitialize]
        public static void ClassInitialize(TestContext testContext)
        {
            UnitTestBase<IChromosome, Chromosome>.ClassInitialize(testContext);
        }

        [ClassCleanup]
        public static void ClassCleanup()
        {
            UnitTestBase<IChromosome, Chromosome>.ClassCleanup();
        }

        [TestInitialize]
        public override void TestInitialize()
        {
            base.TestInitialize();
        }

        [TestCleanup]
        public override void TestCleanup()
        {
            base.TestCleanup();
        }
        #endregion UnitTestBase methods

        [TestMethod]
        public void WithMockChromosome_IsValid_IsValidInvokesRootGene()
        {
            // state - WithMockChromosome
            var mock = mocks.DynamicMock<IGene>();

            // Expectation - IsValidInvokesRootGene
            using (mocks.Record())
                Expect.Call(mock.IsValid).Return(true);

            // action - IsValid
            // verify
            curElement.RootGene = mock;
            Assert.IsTrue(curElement.IsValid == true);
            mocks.VerifyAll();
        }

        [TestMethod]
        public void SetRootGene_WithMockGene_MockGeneParentChromosomeIsSet()
        {
            // state - SetRootGene
            var mock = mocks.StrictMock<IGene>();

            // Expectation - MockGeneParentChromosomeIsSet
            using (mocks.Record())
                mock.ParentChromosome = curElement;

            // action - WithMockGene
            curElement.RootGene = mock;

            // verify
            mocks.VerifyAll();
        }

        [TestMethod]
        public void WithMockGene_Fix_CallsMockFix()
        {
            // state - WithMockChromosome
            var mock = mocks.DynamicMock<IGene>();

            // Expectation - CallsMockFix
            using (mocks.Record())
                mock.Fix();

            // Action - Fix
            curElement.RootGene = mock;
            curElement.Fix();

            // verify
            mocks.VerifyAll();
        }

        [TestMethod]
        public void WithMockGene_GetStringDisplay_CallsMockGetStringDisplay()
        {
            // state - WithMockChromosome
            var mock = mocks.DynamicMock<IGene>();

            // Expectation - CallsMockGetStringDisplay
            using (mocks.Record())
                Expect.Call(mock.GetStringDisplay()).Return(TestStrings[0]);

            // Action - GetStringDisplay
            curElement.RootGene = mock;
            Assert.IsTrue(curElement.GetStringDisplay() == TestStrings[0]);

            // verify
            mocks.VerifyAll();
        }

        [TestMethod]
        [Ignore]
        [Bug("Rhino mocks doesn't mock out ToString")]
        public void WithMockGene_ToString_CallsMockToString()
        {
            // state - WithMockChromosome
            var mock = mocks.DynamicMock<IGene>();

            // Expectation - CallsMockGetStringDisplay
            using (mocks.Record())
                Expect.Call(mock.ToString()).Return(TestStrings[0]);

            // Action - GetStringDisplay
            curElement.RootGene = mock;
            Assert.IsTrue(curElement.ToString() == TestStrings[0]);

            // verify
            mocks.VerifyAll();
        }

        [TestMethod]
        public void WithMockParentIndividual_GetParentGenticProgram_InvokesParentIndividualGeneticProgram()
        {
            // state - WithMockParentIndividual
            var mock = mocks.StrictMock<IIndividual>();
            curElement.ParentIndividual = mock;
            var mockGP = mocks.DynamicMock<IGeneticProgram>();

            // Expectation - InvokesParentIndividualGeneticProgram
            using (mocks.Record())
                Expect.Call(mock.ParentGeneticProgram).Return(mockGP);

            // action - GetParentGenticProgram
            Assert.IsTrue(curElement.ParentGeneticProgram == mockGP);
            mocks.VerifyAll();
        }

        [TestMethod]
        public void MockChromosomeInIoC_CloneChild_ReturnsChildFromIoC()
        {
            // state - MockChromosomeInIoC
            var mock = mocks.DynamicMock<IChromosome>();
            IoC.Register<IChromosome>(mock);

            // avoid irrelevant error
            curElement.RootGene = mocks.DynamicMock<IGene>();

            // action - CloneChild
            var result = curElement.CloneChild(null);

            // Expectation - ReturnsChildFromIoC
            Assert.IsTrue(result == mock);
        }

        [TestMethod]
        public void MockChromosomeInIoCAndMockParentIndividual_CloneChild_ReturnsChildFromIoCWithParentIndividual()
        {
            // state - MockChromosomeInIoCAndMockGeneticProgram
            var mock = mocks.DynamicMock<IChromosome>();
            IoC.Register<IChromosome>(mock);
            var mockIndividual = mocks.StrictMock<IIndividual>();

            // avoid irrelevant error
            curElement.RootGene = mocks.DynamicMock<IGene>();

            // Expectation - ReturnsChildFromIoCWithParentIndividual
            using(mocks.Record())
                mock.ParentIndividual = mockIndividual;

            // action - CloneChild
            var result = curElement.CloneChild(mockIndividual);

            // verify
            mocks.Verify(mock);
        }

        [TestMethod]
        public void MockChromosomeInIoCAndMockRootGene_CloneChild_ReturnsChildFromIoCWithRootGeneCloneChild()
        {
            // state - MockChromosomeInIoCAndMockRootGene
            var mock = mocks.DynamicMock<IChromosome>();
            IoC.Register<IChromosome>(mock);
            var mockGene1 = mocks.DynamicMock<IGene>();
            var mockGene2 = mocks.DynamicMock<IGene>();


            // Expectation - ReturnsChildFromIoCWithRootGeneCloneChild
            using (mocks.Record())
            {
                Expect.Call(mockGene1.ChildClone(null, mock)).Return(mockGene2);
                mock.RootGene = mockGene2;
            }

            // action - CloneChild
            curElement.RootGene = mockGene1;
            var result = curElement.CloneChild(null);

            // verify
            mocks.Verify(mockGene1);
        }
    }
}
